package cn.b.sky.shop.activiti.service.impl;

import cn.b.sky.shop.activiti.constans.GlobalDefine;
import cn.b.sky.shop.activiti.dao.LeaveDao;
import cn.b.sky.shop.activiti.model.Leave;
import cn.b.sky.shop.activiti.service.CustomGroupAndRoleService;
import cn.b.sky.common.model.Page;
import org.activiti.engine.*;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.history.HistoricProcessInstance;
import org.activiti.engine.history.HistoricProcessInstanceQuery;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.runtime.ProcessInstanceQuery;
import org.activiti.engine.task.Task;
import org.activiti.engine.task.TaskQuery;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 请假流程Service
 *
 * @author HenryYan
 */
@Service("workflowService")
public class LeaveWorkflowService {

  private static final Logger LOGGER= LoggerFactory.getLogger(LeaveWorkflowService.class);

  @Autowired
  private LeaveDao leaveDao;

  @Autowired
  private RuntimeService runtimeService;

  @Autowired
  protected TaskService taskService;

  @Autowired
  protected HistoryService historyService;

  @Autowired
  protected RepositoryService repositoryService;

  @Autowired
  private IdentityService identityService;

  @Resource
  private CustomGroupAndRoleService customGroupAndRoleService;

  /**
   * 启动流程
   *
   * @param entity
   */
  public ProcessInstance startWorkflow(Leave entity, Map<String, Object> variables) {
    entity.setApplyTime(new Date());
    leaveDao.saveLeave(entity);
    LOGGER.debug("save entity: {}", entity);

    String businessKey = entity.getBusinessKey();

    ProcessInstance processInstance = null;
    String tenantId = (String) variables.get(GlobalDefine.WorkFlow.CUREENTSITECODE);
    try {
      // 用来设置启动流程的人员ID，引擎会自动把用户ID保存到activiti:initiator中
      identityService.setAuthenticatedUserId(entity.getUserId());

      processInstance = runtimeService.startProcessInstanceByKeyAndTenantId("leave", businessKey, variables, tenantId);
      String processInstanceId = processInstance.getId();
      entity.setProcessInstanceId(processInstanceId);
      LOGGER.debug("start process of {key={}, bkey={}, pid={}, variables={}}", new Object[] { "leave", businessKey,
          processInstanceId, variables });
    } finally {
      identityService.setAuthenticatedUserId(null);
    }
    return processInstance;
  }

  public void saveLeave(Leave leave) {
    leave.setApplyTime(new Date());
    leaveDao.saveLeave(leave);
  }

  /**
   * 查询待办任务
   *
   * @param userId 用户ID
   * @return
   */
  public List<Leave> findTasks(String userId, String tenantId, Page page) {
    List<Leave> results = new ArrayList<Leave>();
    List<String> candidateGroups = customGroupAndRoleService.findGroupsAndRolesStrByUser(userId, tenantId);
    // 根据当前人的ID查询
    TaskQuery taskQuery = taskService.createTaskQuery().taskTenantId(tenantId);
    List<Task> tasks = taskQuery.or().taskAssignee(userId).taskCandidateUser(userId)
        .taskCandidateGroupIn(candidateGroups).listPage(page.getStartRow() - 1, page.getEndRow() - 1);

    // 根据流程的业务ID查询实体并关联
    for (Task task : tasks) {
      String processInstanceId = task.getProcessInstanceId();
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
          .processInstanceId(processInstanceId).active().singleResult();
      String businessKey = processInstance.getBusinessKey();
      if (businessKey == null) {
        continue;
      }
      Leave leave = leaveDao.getLeaveByBussinessId(businessKey);
      leave.setTask(task);
      leave.setProcessInstance(processInstance);
      leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
      results.add(leave);
    }

    page.setTotalCount(taskQuery.count());
    page.setData(results);
    return results;
  }

  /**
   * 读取运行中的流程
   *
   * @return
   */
  @Transactional(readOnly = true)
  public List<Leave> findRunningProcessInstaces(Page page) {
    List<Leave> results = new ArrayList<Leave>();
    ProcessInstanceQuery query = runtimeService.createProcessInstanceQuery().processDefinitionKey("leave").active()
        .orderByProcessInstanceId().desc();
    List<ProcessInstance> list = query.listPage(page.getStartRow(), page.getEndRow());

    // 关联业务实体
    for (ProcessInstance processInstance : list) {
      String businessKey = processInstance.getBusinessKey();
      if (businessKey == null) {
        continue;
      }
      Leave leave = leaveDao.getLeaveByBussinessId(businessKey);
      leave.setProcessInstance(processInstance);
      leave.setProcessDefinition(getProcessDefinition(processInstance.getProcessDefinitionId()));
      results.add(leave);

      // 设置当前任务信息
      List<Task> tasks = taskService.createTaskQuery().processInstanceId(processInstance.getId()).active()
          .orderByTaskCreateTime().desc().listPage(0, 1);
      leave.setTask(tasks.get(0));
    }

    page.setTotalCount(query.count());
    page.setData(results);
    return results;
  }

  /**
   * 读取已结束中的流程
   *
   * @return
   */
  @Transactional(readOnly = true)
  public List<Leave> findFinishedProcessInstaces(Page page) {
    List<Leave> results = new ArrayList<Leave>();
    HistoricProcessInstanceQuery query = historyService.createHistoricProcessInstanceQuery()
        .processDefinitionKey("leave").finished().orderByProcessInstanceEndTime().desc();
    List<HistoricProcessInstance> list = query.listPage(page.getStartRow(), page.getEndRow());

    // 关联业务实体
    for (HistoricProcessInstance historicProcessInstance : list) {
      String businessKey = historicProcessInstance.getBusinessKey();
      Leave leave = leaveDao.getLeaveByBussinessId(businessKey);
      leave.setProcessDefinition(getProcessDefinition(historicProcessInstance.getProcessDefinitionId()));
      leave.setHistoricProcessInstance(historicProcessInstance);
      results.add(leave);
    }
    page.setTotalCount(query.count());
    page.setData(results);
    return results;
  }

  /**
   * 查询流程定义对象
   *
   * @param processDefinitionId 流程定义ID
   * @return
   */
  protected ProcessDefinition getProcessDefinition(String processDefinitionId) {
    return repositoryService.createProcessDefinitionQuery()
        .processDefinitionId(processDefinitionId).singleResult();
  }

  public Leave getLeaveByBussinessKey(String bussinesskey) {

    return leaveDao.getLeaveByBussinessId(bussinesskey);
  }

  public Leave getLeaveById(Long id) {
    return leaveDao.getLeaveById(id);
  }

  public void completeTask(String taskId, Map<String, Object> flowMap, Map<String, Object> operationMap) {
    flowMap.put(GlobalDefine.WorkFlow.OPERATIONMAP, operationMap);
    String ispass = "";
    if (flowMap.get("ispass") != null) {
      ispass = (String) flowMap.get("ispass");
    }
    if (ispass != null) {
      flowMap.put("deptLeaderPass", "0".equals(ispass) ? true : false);
      flowMap.remove("ispass");
    }
    //完成任务时触发一个event
    this.taskService.complete(taskId, flowMap);
  }

  public void deptAudit(DelegateTask task, String eventName) {
    if (TaskListener.EVENTNAME_COMPLETE.endsWith(eventName)) {
      //获取业务数据处理
      task.removeVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      String ispass = "";
      if (task.getVariable("ispass") != null) {
        ispass = (String) task.getVariable("ispass");
      }
      if (!StringUtils.isBlank(ispass)) {
        task.setVariable("deptLeaderPass", "0".equals(ispass) ? true : false);
        task.removeVariable("ispass");
      }
    }
  }

  public void hrAudit(DelegateTask task, String eventName) {
    if (TaskListener.EVENTNAME_COMPLETE.endsWith(eventName)) {
      //获取业务数据处理
      task.removeVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      String ispass = "";
      if (task.getVariable("ispass") != null) {
        ispass = (String) task.getVariable("ispass");
      }
      if (!StringUtils.isBlank(ispass)) {
        task.setVariable("hrPass", "0".equals(ispass) ? true : false);
        task.removeVariable("ispass");
      }
    }
  }

  public void reApplyLeave(DelegateTask task, String eventName) {
    /*if (TaskListener.EVENTNAME_COMPLETE.endsWith(eventName)) {
      String processInstanceId = task.getProcessInstanceId();
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
          .processInstanceId(processInstanceId).singleResult();
      //Leave leave = this.getLeaveByBussinessKey(processInstance.getBusinessKey());
      @SuppressWarnings("unchecked")
      Map<String, Object> operationMap = (Map<String, Object>) task.getVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      PropertiesDataBinder dataBinder = PropertiesDataBinder.createBinder(BeanUtils.instantiateClass(Leave.class));
      Leave leave = (Leave) dataBinder.getTarget(operationMap);
      leave.setBusinessKey(processInstance.getBusinessKey());
      leaveDao.updateLeaveByBusinessKey(leave);
      //获取业务数据处理
      task.removeVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      String ispass = "";
      if (task.getVariable("ispass") != null) {
        ispass = (String) task.getVariable("ispass");
      }
      if (!StringUtils.isBlank(ispass)) {
        task.setVariable("reApply", "0".equals(ispass) ? true : false);
        task.removeVariable("ispass");
      }
    }*/
  }

  //重新申请
  public void reportBackEndProcessor(DelegateTask task, String eventName) {
   /* if (TaskListener.EVENTNAME_COMPLETE.endsWith(eventName)) {
      String processInstanceId = task.getProcessInstanceId();
      ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
          .processInstanceId(processInstanceId).singleResult();
      Leave leave = this.getLeaveByBussinessKey(processInstance.getBusinessKey());
      //获取业务数据处理
      @SuppressWarnings("unchecked")
      Map<String, Object> operationMap = (Map<String, Object>) task.getVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      String realityStartTime = (String) operationMap.get("realityStartTime");
      try {
        if (!StringUtils.isBlank(realityStartTime)) {
          leave.setRealityStartTime(DateUtils.getDateUtils().parse(realityStartTime));
        }

        String realityEndTime = (String) operationMap.get("realityEndTime");
        if (!StringUtils.isBlank(realityEndTime)) {
          leave.setRealityEndTime(DateUtils.getDateUtils().parse(realityEndTime));
        }
      } catch (ParseException e) {
        LOGGER.error("{}", e);
        throw new InfoException(e.getMessage());
      }
      leaveDao.updateLeaveById(leave);
      task.removeVariable(GlobalDefine.WorkFlow.OPERATIONMAP);
      if (task.getVariable("ispass") != null) {
        task.removeVariable("ispass");
      }
    }*/
  }

  /**
   * 
   * <strong>Title : claimTask<br></strong>
   * <strong>Description : </strong>签收任务<br> 
   * <strong>Create on : 2015-11-2 下午6:50:59<br></strong>
   * <p>
   * @param taskId
   * @param userId
   * void
   * @throws 
   * @author lidapeng<br>
   * @version <strong>v1.0.0</strong><br>
   * <br>
   * <strong>修改历史:</strong><br>
   * 修改人 | 修改日期 | 修改描述<br>
   * -------------------------------------------<br>
   * <br>
   * <br>
   */
  public void claimTask(String taskId, String userId) {
    if (taskId != null) {
      taskService.claim(taskId, userId);
    }
  }

  public Task getTaskByTaskId(String taskId) {
    if (taskId == null) {
      return null;
    }
    return taskService.createTaskQuery().taskId(taskId).singleResult();
  }

}
